package com.ikas.ai.server.module.steady.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ikas.ai.consts.TableDictConsts;
import com.ikas.ai.model.KafkaMeteData;
import com.ikas.ai.server.error.BusinessException;
import com.ikas.ai.server.module.alarm.enums.SolvedEnum;
import com.ikas.ai.server.module.appraise.enums.StatusEnum;
import com.ikas.ai.server.module.data.model.dto.RealDataHis;
import com.ikas.ai.server.module.data.tdDao.TdDataHisMapper;
import com.ikas.ai.server.module.steady.dao.SteadyAlarmDataMapper;
import com.ikas.ai.server.module.steady.dao.SteadyMonitorMeteMapper;
import com.ikas.ai.server.module.steady.delaytask.SteadyDelayService;
import com.ikas.ai.server.module.steady.enums.*;
import com.ikas.ai.server.module.steady.model.dto.StyMonMeteQueryDto;
import com.ikas.ai.server.module.steady.model.po.SteadyAlarmData;
import com.ikas.ai.server.module.steady.model.po.SteadyMonitorMete;
import com.ikas.ai.server.module.steady.model.po.SteadyStateMete;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 稳态监测测点配置表 服务实现类
 * </p>
 *
 * @author wuyf
 * @since 2023-12-13
 */
@Slf4j
@Service
public class SteadyMonitorMeteService extends ServiceImpl<SteadyMonitorMeteMapper, SteadyMonitorMete> {

    @Resource
    private SteadyStateMeteService steadyStateMeteService;

    @Resource
    private TdDataHisMapper dataHisTdMapper;

    @Resource
    private SteadyAlarmDataMapper steadyAlarmDataMapper;
    @Resource
    private SteadyMonitorMeteMapper steadyMonitorMeteMapper;
    @Resource
    private SteadyDelayService steadyDelayService;


    private static final List<String> PROCESSING_METE = Lists.newArrayList("1CRK00_MODE_DZ_G", "1CRK00_MODE_DZ_P", "1CRK00_MODE_DZ_PC", "2CRK00_MODE_DZ_G", "2CRK00_MODE_DZ_P", "2CRK00_MODE_DZ_PC", "3CRK00_MODE_DZ_G", "3CRK00_MODE_DZ_P", "3CRK00_MODE_DZ_PC", "4CRK00_MODE_DZ_G", "4CRK00_MODE_DZ_P", "4CRK00_MODE_DZ_PC");

    private static final List<String> STOP_METE = Lists.newArrayList("1CRK00_MODE_DZ_STL", "2CRK00_MODE_DZ_STL", "3CRK00_MODE_DZ_STL", "4CRK00_MODE_DZ_STL");


    private List<SteadyMonitorMete> queryWrapperList(StyMonMeteQueryDto queryDto) {
        LambdaQueryWrapper<SteadyMonitorMete> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotEmpty(queryDto.getSteadyType()), SteadyMonitorMete::getSteadyType, queryDto.getSteadyType());
        queryWrapper.eq(StringUtils.isNotBlank(queryDto.getMachineNo()), SteadyMonitorMete::getMachineNo, queryDto.getMachineNo());
        queryWrapper.eq(StringUtils.isNotBlank(queryDto.getMeteCode()), SteadyMonitorMete::getMeteCode, queryDto.getMeteCode());
        queryWrapper.like(StringUtils.isNotBlank(queryDto.getMeteName()), SteadyMonitorMete::getMeteName, queryDto.getMeteName());
        queryWrapper.eq(ObjectUtils.isNotEmpty(queryDto.getMonitorType()), SteadyMonitorMete::getMonitorType, queryDto.getMonitorType());
        queryWrapper.eq(ObjectUtils.isNotEmpty(queryDto.getStatus()), SteadyMonitorMete::getStatus, queryDto.getStatus());
        queryWrapper.orderByAsc(SteadyMonitorMete::getMachineNo).orderByDesc(SteadyMonitorMete::getCreateTime);
        return this.list(queryWrapper);
    }

    private List<SteadyMonitorMete> getByMeteCodeAndValidData(String meteCode) {
        StyMonMeteQueryDto queryDto = new StyMonMeteQueryDto();
        queryDto.setMeteCode(meteCode);
        queryDto.setStatus(StatusEnum.VALID.getCode());
        return queryWrapperList(queryDto);
    }



    public SteadyMonitorMete detail(Long id) {
        return this.getById(id);
    }

    /**
     * 处理kafka的稳态类型测点数据
     *
     * @param meteData kafka data
     */
    public void handleKafkaDataOfStateMeteType(KafkaMeteData meteData) {
        steadyStateMeteService.handleKafkaData(meteData);
    }

    /**
     * 处理kafka的监测类型测点数据
     *
     * @param meteData kafka data
     */
    public void handleKafkaDataOfMonitorMeteType(KafkaMeteData meteData) {
        log.info("开始处理kafka过来的监测类型测点数据：{}", meteData);
        triggerMonitorMete(meteData.getMeteId(), meteData.getMeteCode(), meteData.getValue(), meteData.getGenerateTime());
        log.info("处理kafka过来的监测类型测点【{}】数据结束", meteData.getMeteCode());
    }

    /**
     * 触发配置监测测点
     *
     * @param meteCode     测点编号
     * @param meteValue    测点值
     * @param generateTime 测点上报时间
     */
    public void triggerMonitorMete(Long meteId, String meteCode, String meteValue, Long generateTime) {
        // 获取当前测点已配置的运行稳态预警或停机稳态预警
        List<SteadyMonitorMete> monitorMetes = getByMeteCodeAndValidData(meteCode);
        if (CollectionUtils.isEmpty(monitorMetes)) {
            log.info("处理结果：未找到可触发的监测类型测点【{}】的数据，generateTime：{}", meteCode, generateTime);
            return;
        }
        if (StringUtils.isBlank(meteValue)) {
            log.info("处理结果：测点【{}】的数字为空，generateTime：{}", meteCode, generateTime);
            return;
        }
        for (SteadyMonitorMete monitorMete : monitorMetes) {
            List<SteadyStateMete> stateMetes = steadyStateMeteService.getByMachineNo(monitorMete.getMachineNo());
            List<SteadyStateMete> stateMeteList;
            if (Objects.equals(SteadyTypeEnum.RUNNING_STEADY.getValue(), monitorMete.getSteadyType())) {
                //运行稳态，如果全是2或者全是0，不生成运行稳态预警
                stateMeteList = stateMetes.stream().filter(i -> PROCESSING_METE.contains(i.getMeteCode())).filter(
                        i -> !SteadyExecStatusEnum.COMPLETE.getValue().equals(i.getSteadyStatus())).filter(
                                i -> !SteadyExecStatusEnum.NOT_START.getValue().equals(i.getSteadyStatus())).collect(Collectors.toList());
                log.info("机组对应不为2或者0的运行稳态测点，稳态测点:{}", JSON.toJSONString(stateMeteList));
            } else {
                //停机稳态,如果是2，不生成停机稳态预警
                stateMeteList = stateMetes.stream().filter(i -> STOP_METE.contains(i.getMeteCode())).filter(
                        i -> !SteadyExecStatusEnum.COMPLETE.getValue().equals(i.getSteadyStatus())).filter(
                                i -> !SteadyExecStatusEnum.NOT_START.getValue().equals(i.getSteadyStatus())).collect(Collectors.toList());
                log.info("机组对应不为2或者0的停机稳态测点，稳态测点:{}", JSON.toJSONString(stateMeteList));
            }
            // 如果size等于，则说明当前测点对应的机组并没有处于运行稳态或者停机稳态，就不用往下执行了
            if (stateMeteList.size() == 0) {
                continue;
            }
            //监测类型 0：阈值监测，1：趋势监测
            Integer monitorType = monitorMete.getMonitorType();
            if (SteadyMonitorTypeEnum.TREND.getValue().equals(monitorType)) {
                // 趋势监测逻辑处理
                Integer seconds = monitorMete.getTrendDuration();
                //预警条件
                AlarmConditionEnum alarmCondition = AlarmConditionEnum.getEnumByValue(monitorMete.getAlarmCondition());
                log.info("alarmCondition:{}", alarmCondition);
                //校验是否满足条件
                Double subVal = judgeConditionsAndGetSubVal(monitorMete.getMeteId(),
                        seconds, alarmCondition,
                        monitorMete.getAlarmThreshold(), meteValue, generateTime, monitorType);
                log.info("趋势变化值:{}", subVal);
                //如果判断满足条件，>-1时，生成稳态预警数据
                if (subVal > -1.0) {
                    log.info("处理结果：测点【{}】满足触发条件，generateTime：{}", meteCode, generateTime);
                    log.info("开始生成预警数据");
                    //生成一条稳态预警数据
                    createSteadyAlarmData(monitorMete, meteValue, subVal, generateTime);
                    log.info("生成预警数据完成");
                }
            } else if (SteadyMonitorTypeEnum.THRESHOLD.getValue().equals(monitorType)) {
                // 阈值监测逻辑处理
                // 1.获取延迟时间
                Integer seconds = monitorMete.getDelayAlarmDuration();
                // 预警条件
                AlarmConditionEnum alarmCondition = AlarmConditionEnum.getEnumByValue(monitorMete.getAlarmCondition());
                log.info("alarmCondition:{}", alarmCondition);
                // 如果当前值未超出阈值，则无需创建延时队列，因为永远不可能预警
                if (isMeetCondition2(monitorMete.getAlarmThreshold(), Double.valueOf(meteValue), alarmCondition)) {
                    if (seconds == 0) {
                        // 生成预警记录，状态为已预警
                        createSteadyAlarmData(monitorMete, meteValue, 0, generateTime, DelayStatusEnum.ALARMED.getValue());
                    } else {
                        try {
                            // 生成预警记录，状态为延时未预警
                            SteadyAlarmData steadyAlarmData = createSteadyAlarmData(monitorMete, meteValue, 0, generateTime, DelayStatusEnum.DELAY_PENDING_ALARM.getValue());
                            if (meteId != null && steadyAlarmData.getId() != null) {
                                steadyDelayService.produce(meteId, steadyAlarmData.getId(), steadyAlarmData.getAlarmTime().getTime(), seconds);
                            }
                        } catch (Exception e) {
                            log.error("创建延时任务失败：" + e.getMessage());
                            throw new BusinessException("创建延时任务失败");
                        }
                    }
                }
            }
        }
    }


    /**
     * 判断是否符合阈值监测条件并获取趋势变化值
     *
     * @param second         预警延迟时长 秒
     * @param alarmCondition 预警条件
     * @param alarmValue     预警阈值
     * @param meteValue      当前测点值
     * @param generateTime   当前测点时间
     * @return boolean
     */
    private Double judgeConditionsAndGetSubVal(Long meteId,
                                               Integer second,
                                               AlarmConditionEnum alarmCondition,
                                               Double alarmValue,
                                               String meteValue,
                                               Long generateTime,
                                               Integer monitorType) {
        Double nowValue = Double.parseDouble(meteValue);
        double subValue = -1.0;
        //从tdEngine获取历史数据得到范围内的最大值或最小值
        Double extremeValue = getExtremeValueFromTdTrend(meteId, second, generateTime, alarmCondition, monitorType);
        log.info("历史数据值:{}", extremeValue);
        if (Double.valueOf(-1.0).equals(extremeValue) || -1.0 == extremeValue) {
            return subValue;
        }
        //是否符合条件flag
        if (isMeetCondition(alarmValue, nowValue, alarmCondition, extremeValue)) {
            subValue = Math.abs(nowValue - extremeValue);
            log.info("subValue:{}", subValue);
        } else {
            log.info("不符合触发条件的具体情况：" +
                    "当前测点值：{}，" +
                    "阈值条件：{}，" +
                    "阈值：{}，" +
                    "预警时长：{}(s)", alarmValue, meteValue, alarmCondition.getDesc(), second);
        }
        return subValue;
    }

    /**
     * 判断是否符合监测条件
     *
     * @param alarmValue     预警值
     * @param nowValue       当前测点值
     * @param alarmCondition 条件枚举类
     * @param extremeValue   测点历史数据的极值
     * @return boolean
     */
    private boolean isMeetCondition(Double alarmValue,
                                    Double nowValue,
                                    AlarmConditionEnum alarmCondition,
                                    Double extremeValue) {
        boolean meetFlag = false;
        switch (alarmCondition) {
            case GT:
                //条件：>，符合标准：最小值>阈值且当前值>阈值
                meetFlag = extremeValue > alarmValue && nowValue > alarmValue;
                break;
            case GE:
                //条件：>=，符合标准：最小值>=阈值且当前值>=阈值
                meetFlag = extremeValue >= alarmValue && nowValue >= alarmValue;
                break;
            case LT:
                //条件：<，符合标准：最大值<阈值且当前值<阈值
                meetFlag = extremeValue < alarmValue && nowValue < alarmValue;
                break;
            case LE:
                //条件：<=，符合标准：最大值<=阈值且当前值<=阈值
                meetFlag = extremeValue <= alarmValue && nowValue <= alarmValue;
                break;
            case UP:
                //条件：上升，符合标准：当前值-最小值>阈值
                if (nowValue > extremeValue) {
                    meetFlag = Math.abs(nowValue - extremeValue) > alarmValue;
                }
                break;
            case DW:
                //条件：下降，符合标准：最大值-当前值<阈值
                if (nowValue < extremeValue) {
                    meetFlag = Math.abs(nowValue - extremeValue) > alarmValue;
                }
                break;
            default:
                break;
        }
        return meetFlag;
    }

    /**
     * 用于判断阈值检测预警条件是否触发
     *
     * @param alarmValue     预警值
     * @param nowValue       当前测点值，或者是某个区间内的最大值/最小值
     * @param alarmCondition 条件枚举类
     * @return boolean
     */
    public boolean isMeetCondition2(Double alarmValue,
                                     Double nowValue,
                                     AlarmConditionEnum alarmCondition) {
        boolean meetFlag = false;
        switch (alarmCondition) {
            case GT:
                //条件：>，符合标准：当前值/某区间最大值/某区间最小值 > 预警值
                meetFlag = nowValue > alarmValue;
                break;
            case GE:
                //条件：>=，符合标准：当前值/某区间最大值/某区间最小值 >= 预警值
                meetFlag = nowValue >= alarmValue;
                break;
            case LT:
                //条件：<，符合标准：当前值/某区间最大值/某区间最小值 < 预警值
                meetFlag = nowValue < alarmValue;
                break;
            case LE:
                //条件：<=，符合标准：当前值/某区间最大值/某区间最小值 <= 预警值
                meetFlag = nowValue <= alarmValue;
                break;
            default:
                break;
        }
        return meetFlag;
    }

    /**
     * 从tdEngine获取历史数据得到范围内的最大值或最小值
     *
     * @param meteId         测点id
     * @param startTimeLong  查询起始时间
     * @param endTimeLong    查询结束时间
     * @param alarmCondition 当前条件
     * @return Double
     */
    public Double getExtremeValueFromTd(Long meteId,
                                         Long startTimeLong,
                                         Long endTimeLong,
                                         AlarmConditionEnum alarmCondition,
                                         Integer monitorType) {
        String tableName = TableDictConsts.DATA_HIS_PREFIX_YC + meteId;
        Timestamp startTime = new Timestamp(startTimeLong);
        Timestamp endTime = new Timestamp(endTimeLong);
        List<RealDataHis> tdDataList;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        log.info("tdengine开始时间：" + simpleDateFormat.format(startTime));
        log.info("tdengine结束时间：" + simpleDateFormat.format(endTime));
        if (SteadyMonitorTypeEnum.THRESHOLD.getValue().equals(monitorType)) {
            //如果是阈值预警，包含当前测点
            tdDataList = dataHisTdMapper.selectByTableNameTime(tableName, startTime, endTime);
        } else {
            tdDataList = dataHisTdMapper.selectByTableNameAndTime(tableName, startTime, endTime);
        }
        log.info("td历史数据：{}", JSON.toJSONString(tdDataList));
        if (CollectionUtils.isEmpty(tdDataList)) {
            return -1.0;
        }
        String maxValue = tdDataList.stream().max(Comparator.comparing(i -> Double.valueOf(i.getValue())))
                .orElse(new RealDataHis()).getValue();
        String minValue = tdDataList.stream().min(Comparator.comparing(i -> Double.valueOf(i.getValue())))
                .orElse(new RealDataHis()).getValue();
        Integer minSign = 0;
        if (alarmCondition.getGroupVal().equals(minSign)) {
            log.info("最小值：" + minValue);
            return Double.parseDouble(minValue);
        }
        log.info("最大值：" + maxValue);
        return Double.parseDouble(maxValue);
    }


    /**
     * 供趋势逻辑使用
     * @param meteId
     * @param second
     * @param generateTime
     * @param alarmCondition
     * @param monitorType
     * @return
     */
    private Double getExtremeValueFromTdTrend(Long meteId,
                                         Integer second,
                                         Long generateTime,
                                         AlarmConditionEnum alarmCondition,
                                         Integer monitorType) {
        String tableName = TableDictConsts.DATA_HIS_PREFIX_YC + meteId;
        Timestamp endTime = new Timestamp(generateTime);
        long startMillSecond = endTime.getTime() - second * 1000L;
        Timestamp startTime = new Timestamp(startMillSecond);
        List<RealDataHis> tdDataList;
        if (SteadyMonitorTypeEnum.THRESHOLD.getValue().equals(monitorType)) {
            //如果是阈值预警，包含当前测点
            tdDataList = dataHisTdMapper.selectByTableNameTime(tableName, startTime, endTime);
        } else {
            tdDataList = dataHisTdMapper.selectByTableNameAndTime(tableName, startTime, endTime);
        }
        log.info("td历史数据：{}", JSON.toJSONString(tdDataList));
        if (CollectionUtils.isEmpty(tdDataList)) {
            return -1.0;
        }
        String maxValue = tdDataList.stream().max(Comparator.comparing(i -> Double.valueOf(i.getValue())))
                .orElse(new RealDataHis()).getValue();
        String minValue = tdDataList.stream().min(Comparator.comparing(i -> Double.valueOf(i.getValue())))
                .orElse(new RealDataHis()).getValue();
        Integer minSign = 0;
        if (alarmCondition.getGroupVal().equals(minSign)) {
            return Double.parseDouble(minValue);
        }
        return Double.parseDouble(maxValue);
    }

    /**
     * 生成一条预警数据(只针对阈值监测延时预警的逻辑)
     *
     * @param monitorMete  配置监测测点对象
     * @param meteValue    当前测点值
     * @param subVal       趋势变化值
     * @param generateTime 测点上报时间
     * @param delayStatus 延时状态
     */
    @Transactional(rollbackFor = Exception.class)
    public SteadyAlarmData createSteadyAlarmData(SteadyMonitorMete monitorMete, String meteValue,
                                      double subVal, Long generateTime, Integer delayStatus) {
        double nowValue = Double.parseDouble(meteValue);
        SteadyAlarmData alarmData = new SteadyAlarmData();
        alarmData.setDelayStatus(delayStatus);
        alarmData.setMonitorMeteId(monitorMete.getId());
        alarmData.setAlarmTime(new Timestamp(generateTime));
        alarmData.setSteadyType(monitorMete.getSteadyType());
        List<SteadyStateMete> stateMetes = steadyStateMeteService.getByMachineNo(monitorMete.getMachineNo());
        log.info("机组对应稳态测点，稳态类型:{},机组:{}，稳态测点:{}", monitorMete.getSteadyType(), monitorMete.getMachineNo(), JSON.toJSONString(stateMetes));
        //获取当前稳态数据
        SteadyStateMete stateMete = steadyStateMeteService.getByStatusOfProcessing(monitorMete.getMachineNo(), monitorMete.getSteadyType());
        if (stateMete != null) {
            alarmData.setSteadyStartTime(stateMete.getStartTime());
            alarmData.setSteadyDesc(stateMete.getSteadyDesc());
        }
        alarmData.setMeteValue(doubleToBigDecimal(nowValue, 3));
        alarmData.setTrendChangeValue(doubleToBigDecimal(subVal, 3));
        SteadyMonitorMete steadyMonitorMete = steadyMonitorMeteMapper.selectById(alarmData.getMonitorMeteId());
        alarmData.setMachineNo(steadyMonitorMete.getMachineNo());
        alarmData.setMeteCode(steadyMonitorMete.getMeteCode());
        alarmData.setMeteName(steadyMonitorMete.getMeteName());
        alarmData.setMonitorType(steadyMonitorMete.getMonitorType());
        alarmData.setMonitorDesc(steadyMonitorMete.getMonitorDesc());
        alarmData.setDelayAlarmDuration(steadyMonitorMete.getDelayAlarmDuration());
        alarmData.setTrendDuration(steadyMonitorMete.getTrendDuration());
        alarmData.setAlarmCondition(steadyMonitorMete.getAlarmCondition());
        alarmData.setAlarmThreshold(steadyMonitorMete.getAlarmThreshold());
        LambdaQueryChainWrapper<SteadyAlarmData> wrapper = new LambdaQueryChainWrapper<>(steadyAlarmDataMapper);
        Integer count = wrapper.eq(SteadyAlarmData::getMonitorMeteId, monitorMete.getId())
                .eq(SteadyAlarmData::getSolved, SolvedEnum.UN_SOLVED.getSolved())
                .count();
        log.info("是否存在未消缺的预警记录,测点{},count:{}", monitorMete.getId(), count);
        if (count <= 0) {
            //不存在该测点的告警才新增
            steadyAlarmDataMapper.insert(alarmData);
        } else {
            // 如果count=1，则说明在这之前已经产生了预警记录，则需要将记录id设置到alarmData，在创建延时任务时需要用到
            SteadyAlarmData one = wrapper.eq(SteadyAlarmData::getMonitorMeteId, monitorMete.getId())
                    .eq(SteadyAlarmData::getSolved, SolvedEnum.UN_SOLVED.getSolved())
                    .one();
            alarmData.setId(one.getId());
            // 如果存在该预警记录，并且延时状态为延时不预警，那么就更新这条数据，因为走到这一步说明需要重新开启一次预警
            if (one.getDelayStatus() == 3) {
                steadyAlarmDataMapper.updateById(alarmData);
            }
        }
        return alarmData;
    }

    /**
     * 成一条预警数据(只针对趋势监测预警的逻辑)
     * @param monitorMete 配置监测测点对象
     * @param meteValue 当前测点值
     * @param subVal 趋势变化值
     * @param generateTime 测点上报时间
     */
    @Transactional(rollbackFor = Exception.class)
    public void createSteadyAlarmData(SteadyMonitorMete monitorMete, String meteValue,
                                      double subVal, Long generateTime) {
        double nowValue = Double.parseDouble(meteValue);
        SteadyAlarmData alarmData = new SteadyAlarmData();
        alarmData.setMonitorMeteId(monitorMete.getId());
        alarmData.setAlarmTime(new Timestamp(generateTime));
        alarmData.setSteadyType(monitorMete.getSteadyType());
        List<SteadyStateMete> stateMetes = steadyStateMeteService.getByMachineNo(monitorMete.getMachineNo());
        log.info("机组对应稳态测点，稳态类型:{},机组:{}，稳态测点:{}", monitorMete.getSteadyType(), monitorMete.getMachineNo(), JSON.toJSONString(stateMetes));
        //获取当前稳态数据
        SteadyStateMete stateMete = steadyStateMeteService.getByStatusOfProcessing(monitorMete.getMachineNo(), monitorMete.getSteadyType());
        if (stateMete != null) {
            alarmData.setSteadyStartTime(stateMete.getStartTime());
            alarmData.setSteadyDesc(stateMete.getSteadyDesc());
        }
        alarmData.setMeteValue(doubleToBigDecimal(nowValue, 3));
        alarmData.setTrendChangeValue(doubleToBigDecimal(subVal, 3));
        SteadyMonitorMete steadyMonitorMete = steadyMonitorMeteMapper.selectById(alarmData.getMonitorMeteId());
        alarmData.setMachineNo(steadyMonitorMete.getMachineNo());
        alarmData.setMeteCode(steadyMonitorMete.getMeteCode());
        alarmData.setMeteName(steadyMonitorMete.getMeteName());
        alarmData.setMonitorType(steadyMonitorMete.getMonitorType());
        alarmData.setMonitorDesc(steadyMonitorMete.getMonitorDesc());
        alarmData.setDelayAlarmDuration(steadyMonitorMete.getDelayAlarmDuration());
        alarmData.setTrendDuration(steadyMonitorMete.getTrendDuration());
        alarmData.setAlarmCondition(steadyMonitorMete.getAlarmCondition());
        alarmData.setAlarmThreshold(steadyMonitorMete.getAlarmThreshold());
        LambdaQueryChainWrapper<SteadyAlarmData> wrapper = new LambdaQueryChainWrapper<>(steadyAlarmDataMapper);
        Integer count = wrapper.eq(SteadyAlarmData::getMonitorMeteId, monitorMete.getId())
                .eq(SteadyAlarmData::getSolved, SolvedEnum.UN_SOLVED.getSolved())
                .count();
        log.info("是否存在未消缺的预警记录,测点{},count:{}", monitorMete.getId(), count);
        if (count <= 0) {
            //不存在该测点的告警才新增
            steadyAlarmDataMapper.insert(alarmData);
        }
    }

    /**
     * double转BigDecimal
     *
     * @param value value of double
     * @param scale 精度数 保留几位小数
     * @return BigDecimal
     */
    private BigDecimal doubleToBigDecimal(double value, int scale) {
        return BigDecimal.valueOf(value).setScale(scale, RoundingMode.HALF_UP);
    }

}
